const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  #state = PENDING;
  #result = undefined;
  #handlers = [];
  constructor(executor) {
    const resolve = (data) => {
      this.#changeState(FULFILLED, data);
    };
    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }
  #isPromiseLike(value) {
    if (
      value !== null &&
      (typeof value === "object" || typeof value === "function")
    )
      return typeof value.then === "function";
    return false;
  }
  #changeState(state, result) {
    if (this.#state !== PENDING) return;
    this.#state = state;
    this.#result = result;
    this.#run();
  }
  #runMicoTask(callback) {
    if (typeof queueMicrotask !== "function") {
      queueMicrotask(callback);
    } else if (
      typeof process === "object" &&
      typeof process.nextTick === "function"
    ) {
      process.nextTick(callback);
    } else if (typeof MutationObserver === "function") {
      const ob = new MutationObserver(callback);
      const textNode = document.createTextNode("1");
      ob.observe(textNode, {
        characterData: true,
      });
      textNode.data = "2";
    } else {
      setTimeout(callback, 0);
    }
  }
  #run() {
    if (this.#state === PENDING) return;
    while (this.#handlers.length) {
      const { onFulfilled, onRejected, resolve, reject } =
        this.#handlers.shift();
      if (this.#state === FULFILLED) {
        this.#runOne(onFulfilled, resolve, reject);
      } else {
        this.#runOne(onRejected, resolve, reject);
      }
    }
  }
  #runOne(callback, resolve, reject) {
    this.#runMicoTask(() => {
      if (typeof callback !== "function") {
        const settled = this.#state === FULFILLED ? resolve : reject;
        settled(this.#result);
        return;
      }
      try {
        const data = callback(this.#result);
        if (this.#isPromiseLike(data)) {
          data.then(resolve, reject);
        } else {
          resolve(data);
        }
      } catch (error) {
        reject(error);
      }
    });
  }
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this.#handlers.push({
        onFulfilled,
        onRejected,
        resolve,
        reject,
      });
      this.#run();
    });
  }
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }
  finally(onFinally) {
    return this.then(
      (data) => {
        onFinally();
        return data;
      },
      (err) => {
        onFinally();
        throw err;
      }
    );
  }
  static resolve(value) {
    if (value instanceof MyPromise) return value;
    let _resovle, _reject;
    const p = new MyPromise((resolve, reject) => {
      _resovle = resolve;
      _reject = reject;
    });
    if (p.#isPromiseLike(value)) {
      value.then(_resovle, _reject);
    } else {
      _resovle(value);
    }
    return p;
  }
  static reject(reason) {
    return new MyPromise((_resolve, reject) => {
      reject(reason);
    });
  }
   static all(promises) {
          const results = [];
           return new MyPromise((resolve, reject) => {
               promises.forEach(promise => {
                   if (promise.#state ==FULFILLED) {
                        results.push(promise.#result)
                   } else if (promise.#state == REJECTED) {
                       reject(promise.#result)
                   }
                   if (results.length == promises.length) {
                       resolve(values)
                   }
               });
           })
       }
   ​
       //Promise的静态方法，race
       static race(promises) {
           return new MyPromise((resolve, reject) => {
               promises.forEach(promise => {
                   promise.then(value => {
                       resolve(value)
                   })
               });
           })
       }
   ​
}
// const p = new MyPromise((resolve, reject) => {
//   setTimeout(() => {
//     resolve(1);
//   });
// }, 1000);
// p.then((data) => {
//   console.log(data, "成功1");
//   throw 456;
// }).then(
//   (data) => {
//     console.log(data, "===ok");
//   },
//   (err) => {
//     console.log(err, "err");
//   }
// );
function test() {
  return new MyPromise((resolve, reject) => {
    reject(1);
  });
}
async function test1() {
  try {
    const a = await test();
    console.log(a, "===a");
  } catch (error) {
    console.log(error, "==e");
  }
}
test1();
